package com.kitty.game.party.service;

import com.kitty.common.db.CacheServiceLJ;
import com.kitty.common.model.Reason;
import com.kitty.common.thread.IdGenerator;
import com.kitty.common.utils.SpringUtils;
import com.kitty.game.ServerService;
import com.kitty.game.activity.model.product.ActivityType;
import com.kitty.game.bangpai.*;
import com.kitty.game.chat.message.RespChat;
import com.kitty.game.config.NPC;
import com.kitty.game.config.Skill;
import com.kitty.game.confirm.model.CreatePartyConfirm;
import com.kitty.game.confirm.model.PartyDonateConfirm;
import com.kitty.game.enter.*;
import com.kitty.game.equip.message.RespNotifyMiscEx;
import com.kitty.game.fight.service.BroadcastService;
import com.kitty.game.friend.model.RoleView;
import com.kitty.game.i18n.I18nId;
import com.kitty.game.i18n.I18nIdDataPool;
import com.kitty.game.mail.model.Mail;
import com.kitty.game.mail.service.MailService;
import com.kitty.game.npc.service.NewNpcService;
import com.kitty.game.party.PartyDataPool;
import com.kitty.game.party.message.RespPartyLog;
import com.kitty.game.party.message.RespPartyNotification;
import com.kitty.game.party.model.*;
import com.kitty.game.pet.PetDataPool;
import com.kitty.game.role.model.Account;
import com.kitty.game.role.model.Role;
import com.kitty.game.role.service.RoleService;
import com.kitty.game.team.message.RespClearnRequest;
import com.kitty.game.team.message.RespConfirm;
import com.kitty.game.team.message.RespMsg;
import com.kitty.game.utils.*;
import com.kitty.game.utils.dirtywords.WordService;
import com.kitty.game.welfare.model.CommonFetchedData;
import com.kitty.listener.EventDispatcher;
import com.kitty.listener.EventType;
import com.kitty.listener.event.PartyCapitalChangeEvent;
import com.kitty.mina.message.Message;
import com.kitty.mina.message.MessagePusher;
import com.kitty.mina.task.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.lang.util.NutMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PreDestroy;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Slf4j
public class PartyService {

    /**帮派日志时间格式*/
    private static final String LOG_DATE_FORMAT = "yyyy-MM-dd HH:mm";

    @Autowired
    RoleService roleService;
    @Autowired
    WordService wordService;
    @Autowired
    CacheServiceLJ cacheServiceLJ;
    @Autowired
    NewNpcService newNpcService;
    @Autowired
    private PartyRedBagHandler redBagHandler;
    @Autowired
    BroadcastService broadcastService;

    /**
     * 加载已有帮派
     */
    public void loadParty() {
        Map<Long, Party> partyMap = new ConcurrentHashMap<>();
        Map<String, Long> name2Ids = new ConcurrentHashMap<>();
        Dao dao = SpringUtils.getBean(Dao.class);
        List<Party> list =dao.query(Party.class, Cnd.NEW());
        for (Party party : list) {
            party.doAfterInit();
            partyMap.put(party.getId(), party);
            name2Ids.put(party.getPartyName(), party.getId());
        }

        PartyDataPool.partyMap = partyMap;
        PartyDataPool.partyName2Id = name2Ids;
    }

    public void loadCommon() {
        Dao dao = SpringUtils.getBean(Dao.class);
        //RoleOfflineData roleOfflineData = dao.fetch(RoleOfflineData.class, "offline_role_party");
        CommonFetchedData roleOfflineData = dao.fetch(CommonFetchedData.class, CommonConst.offline_role_party);
        if (roleOfflineData != null) {
            Map<Long, Long> map = JsonUtils.string2Map(roleOfflineData.getData(), Long.class, Long.class);
            if (map != null) {
                PartyDataPool.offlineRoleParty.putAll(map);
            }
        }
    }

    @PreDestroy
    private void shutDown() {
        saveCommon();
    }

    private void saveCommon() {
        Dao dao = SpringUtils.getBean(Dao.class);
        String data = JsonUtils.map2String(PartyDataPool.offlineRoleParty);
        dao.insertOrUpdate(new CommonFetchedData("offline_role_party", data));
    }

    /**
     * 通过帮派id取帮派
     * @param partyId
     * @return
     */
    public Party getParty(long partyId) {
        return PartyDataPool.partyMap.get(partyId);
    }

    /**通过角色取帮派*/
    public Party getParty(Role role) {
        if (role == null) {return null;}
        return getParty(role.getPartyId());
    }

    /**
     * 取帮派 by Name
     * @param partyName
     * @return
     */
    public Party getPartyByName(String partyName) {
        if (StringUtils.isEmpty(partyName)) {return null;}

        Long partyId = PartyDataPool.partyName2Id.get(partyName);
        if (partyId != null) {
            return getParty(partyId);
        }
        return null;
    }

    /**
     * 请求创建帮派
     * @param role
     * @param partyName
     */
    public void reqCreateParty(Role role, String partyName) {
        if (role == null) {return ;}
        Account account = SpringUtils.getAccountService().getAccount(role.getSid());
        if (account == null){
            MessagePusher.pushMessage(role,new RespNotifyMiscEx("没有账号"));
            return;
        }
//        if (account.getPrivilege()<=100){
//            MessagePusher.pushMessage(role,new RespNotifyMiscEx("没有建立帮派的权限"));
//            return;
//        }
//        if (true){
//            MessagePusher.pushMessage(role,new RespNotifyMiscEx("帮派维护中。。。"));
//            return;
//        }
        /**检测条件是否满足*/
        if (!checkCreateParty(role, partyName)) return;

        role.setConfirm(new CreatePartyConfirm(partyName));

        RespConfirm respConfirm = new RespConfirm();
        respConfirm.setTips(I18nIdDataPool.getI18nContent(I18nId.PMT_363, Const.PARTY_CREATE_NEED_GOLD, partyName));
        respConfirm.setConfirm_type("");
        MessagePusher.pushMessage(role, respConfirm);
    }

    /**
     * 创建帮派
     * @param role
     * @param partyName
     */
    public synchronized void confirmCreateParty(Role role, String partyName) {
        if (role == null) {return ;}

        log.info("{}({})请求创建帮派={}", role.getUid(), role.getName(), partyName);

        /**检测条件是否满足*/
        if (!checkCreateParty(role, partyName)) return;

        /**扣除金元宝*/
        roleService.subtractGold(role, Const.PARTY_CREATE_NEED_GOLD, Reason.CREATE_PARTY);

        /**生成一个新帮派*/
        newParty(role, partyName);
        roleService.refreshRole(role);
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_361, Const.PARTY_CREATE_NEED_GOLD, partyName);
        MessagePusher.pushMessage(role, new RespNotifyMisc(content));

        log.info("{}({})创建帮派:{}成功", role.getUid(), role.getName(), partyName);
        newNpcService.closeDlg(role, "JoinPartyDlg");
        newNpcService.openDlg(role, "PartyInfoTabDlg");
        getParty(role).setIcon("");
        notifyicon(role);
    }

    public void notifyicon(Role role)
    {
        Party party = getParty(role);
        /**还没有帮派*/
        if (party == null) {
            return;
        }
        String fileName = party.getIcon();
        RespPartyIcon icon = new RespPartyIcon();
        icon.setRoleId(role.getRoleId());
        icon.setMd5_value(fileName);
        broadcastService.sendLocalMessage(role, icon);
    }
    /**创建帮派检测*/
    private boolean checkCreateParty(Role role, String partyName) {
        /**检测帮派名称是否合法*/
        boolean check = checkPartyName(role, partyName);
        if (check == false) {
            return false;
        }


        /**是否已经加入帮派*/
        if (isHaveParty(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_302);
            return false;
        }

        /**是否等级足够*/
        if (role.getLevel() < Const.PARTY_CREATE_MIN_LEVEL) {
            MessagePusher.notify2Player(role, I18nId.PMT_303);
            return false;
        }

        /**是否金元宝足够*/
        if (role.getGold() < Const.PARTY_CREATE_NEED_GOLD) {
            MessagePusher.notify2Player(role, I18nId.PMT_403);
            return false;
        }
        return true;
    }

    /**
     * 打开自己的帮派
     * @param role
     */
    public synchronized void openPartyDlg(Role role) {
        Party party = getParty(role);
        if (party == null) {
            return;
        }

        RespOpenPatry respOpenPatry = getRespOpenPatry(party);
        MessagePusher.pushMessage(role, respOpenPatry);
    }

    public RespOpenPatry getRespOpenPatry(Party party) {
        RespOpenPatry respOpenPatry = new RespOpenPatry();
        respOpenPatry.setCreateTime(Math.toIntExact(party.getCreateTime() / TimeUtil.ONE_SECOND));
        respOpenPatry.setCreator(party.getCreater());
        respOpenPatry.setPartyName(party.getPartyName());
        respOpenPatry.setPartyLevel(party.getLevel());
        respOpenPatry.setJianshe(party.getJianshe());
        respOpenPatry.setFenglu(party.getFenglu());
        respOpenPatry.setPartyId(String.valueOf(party.getId()));
        respOpenPatry.setPartyNotice(StringUtils.isNotEmpty(party.getNotice())?party.getNotice():"");
        respOpenPatry.setZijin(party.getCapital());
        respOpenPatry.setTotalMember(getPartyTotalCount(party));
        respOpenPatry.setOnlineMember(getPartyOnlineCount(party));
        respOpenPatry.setHeir(party.getHeir());
        respOpenPatry.setAutoMinTao(party.getAutoAgreeMinTao());
        int k = party.isAutoAgreeWork() == true ? 1 : 0;
        respOpenPatry.setAutoAcceptLevel(100000*party.getAutoAgreeMinLevel()+k);
        respOpenPatry.setIcon_md5( party.getIcon() );
        respOpenPatry.setMemberInfos(getPartyMemberInfos(party));
        respOpenPatry.setSkillInfoList(getPartySkillInfos(party));

        return respOpenPatry;
    }

    /***
     * 取帮派在线人数
     */
    private short getPartyOnlineCount(Party party) {
        if (party == null) {return 0;}

        if (party.getMembers() != null){
            short count = 0;
            Collection<PartyMemberObject> members = party.getMembers().values();
            for (PartyMemberObject member : members) {
                if (roleService.isOnline(member.getRoleUid())) {
                    count += 1;
                }
            }

            return count;
        }

        return 0;
    }

    /**
     * 返回帮派人数
     */
    private short getPartyTotalCount(Party party) {
        if (party == null) {return 0;}

        return (short) party.getMembers().size();
    }

    /**生成一个新帮派*/
    private Party newParty(Role role, String partyName) {
        Party party = new Party();
        party.setCreater(role.getName());
        party.setCapital(2000000000);
        party.setCreateTime(System.currentTimeMillis());
        party.setJianshe(2000000000);
        party.setFenglu(800000);
        party.setLevel((short) 1);
        party.setId(IdGenerator.getNextId());
        party.setPartyName(partyName);
        party.setIcon("default003.png");
        party.setJobs(NutMap.NEW());
        party.getJobs().setv(Const.PARTY_JOB_BANG_ZHU, role.getUid());

        ArrayList<NutMap> skills = new ArrayList<>();
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "神龙罩").setv("skillId", 260).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "五色光环").setv("skillId", 264).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "十万火急").setv("skillId", 181).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "拔苗助长").setv("skillId", 81).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "天生神力").setv("skillId", 31).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "防微杜渐").setv("skillId", 131).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "移花接木").setv("skillId", 263).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "法力护盾").setv("skillId", 262).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "死亡缠绵").setv("skillId", 261).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "漫天血舞").setv("skillId", 257).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "游说之舌").setv("skillId", 255).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "翻转乾坤").setv("skillId", 252).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "乾坤罩").setv("skillId", 259).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "舍身取义").setv("skillId", 265).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "神圣之光").setv("skillId", 253).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "鞭长莫及").setv("skillId", 231).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "舍命一击").setv("skillId", 258).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        {
            NutMap skill = NutMap.NEW();
            skill.setv("skillName", "如意圈").setv("skillId", 254).setv("skillLevel", 0).setv("currJindu", 0).setv("total", 1350000);
            skills.add(skill);
        }
        party.setSkills(skills);

        String job = Const.PARTY_JOB_BANG_ZHU + ":-1";
        addPartyMember(party, role, job);

        PartyDataPool.partyMap.put(party.getId(), party);
        party.save();
        PartyDataPool.partyName2Id.put(party.getPartyName(), party.getId());

        role.setPartyId(party.getId());
        role.save();
        //刷新帮主特权
        List<FiedValue> list = new ArrayList<>();
        list.add(new FiedValue(97, SpringUtils.getPartyService().getPartyJob(role)));
        RespUpdate respUpdate = new RespUpdate();
        respUpdate.setRoleId(role.getRoleId());
        respUpdate.setList(list);
        MessagePusher.pushMessage(role, respUpdate);
        /**添加帮主称号*/
        addPartyTitle(party, role);
        roleService.sendExtraAttribute(role);

        return party;
    }

    /**添加帮派成员*/
    public PartyMemberObject addPartyMember(Party party, Role role, String job) {
        long now = System.currentTimeMillis();
        PartyMemberObject partyMember = new PartyMemberObject(role, now, job);
        party.getMembers().put(partyMember.getRoleUid(), partyMember);
        party.save();
        return partyMember;
    }

    /**添加帮派成员*/
    private PartyMemberObject addPartyMember(Party party, RoleView roleView, String job) {
        long now = System.currentTimeMillis();
        PartyMemberObject partyMember = new PartyMemberObject(roleView, now, job);
        party.getMembers().put(partyMember.getRoleUid(), partyMember);
        party.save();
        return partyMember;
    }

    /**
     * 是否已经加入帮派
     * @param role
     * @return
     */
    private boolean isHaveParty(Role role) {
        return getParty(role.getPartyId()) != null;
    }

    private boolean isHaveParty(String partyName) {
        return getPartyByName(partyName) != null;
    }

    /**
     * 帮派名称是否已经存在
     * @param partyName
     * @return
     */
    private boolean isPartyNameExist(String partyName) {
        return getPartyByName(partyName) != null;
    }

    /**
     * 发送帮派列表
     * @param role
     * @param type
     */
    public synchronized void queryParties(Role role, String type) {
        RespPartyInfo respPartyInfo = new RespPartyInfo();
        respPartyInfo.setOrder(type);
        ArrayList<PartyInfo> partyInfos = new ArrayList<>();
        List<Party> partyList = getSortedParties();
        for (Party party : partyList) {
            short partyTotalCount = getPartyTotalCount(party);
            /*if (getPartyMaxMembers(party.getLevel()) <= partyTotalCount) {
                continue;
            }*/

            PartyInfo partyInfo = new PartyInfo();
            partyInfo.setConstruct(party.getJianshe());
            partyInfo.setLevel(party.getLevel());
            partyInfo.setMembers(partyTotalCount);
            partyInfo.setPartyId(String.valueOf(party.getId()));
            partyInfo.setPartyName(party.getPartyName());
            partyInfos.add(partyInfo);
        }

        respPartyInfo.setList(partyInfos);
        MessagePusher.pushMessage(role, respPartyInfo);
    }

    /**根据名字模糊查找帮派*/
    public synchronized void queryPartiesFuzzyByName(Role role, String keyName) {
        RespPartyInfo respPartyInfo = new RespPartyInfo();
        respPartyInfo.setOrder("fuzzy");
        ArrayList<PartyInfo> partyInfos = new ArrayList<>();
        List<Party> partyList = getSortedParties();
        for (Party party : partyList) {
            /**不包含关键字，跳过*/
            if (!party.getPartyName().contains(keyName)) {continue;}

            short partyTotalCount = getPartyTotalCount(party);
            PartyInfo partyInfo = new PartyInfo();
            partyInfo.setConstruct(party.getJianshe());
            partyInfo.setLevel(party.getLevel());
            partyInfo.setMembers(partyTotalCount);
            partyInfo.setPartyId(String.valueOf(party.getId()));
            partyInfo.setPartyName(party.getPartyName());
            partyInfos.add(partyInfo);
        }

        respPartyInfo.setList(partyInfos);
        MessagePusher.pushMessage(role, respPartyInfo);
    }

    /**根据帮派id模糊查找帮派*/
    public synchronized void queryPartiesFuzzyByNameId(Role role, String keyId) {
        RespPartyInfo respPartyInfo = new RespPartyInfo();
        respPartyInfo.setOrder("exact");
        ArrayList<PartyInfo> partyInfos = new ArrayList<>();
        List<Party> partyList = getSortedParties();
        for (Party party : partyList) {
            /**不包含关键字，跳过*/
            if (!String.valueOf(party.getId()).contains(keyId)) {continue;}

            short partyTotalCount = getPartyTotalCount(party);
            PartyInfo partyInfo = new PartyInfo();
            partyInfo.setConstruct(party.getJianshe());
            partyInfo.setLevel(party.getLevel());
            partyInfo.setMembers(partyTotalCount);
            partyInfo.setPartyId(String.valueOf(party.getId()));
            partyInfo.setPartyName(party.getPartyName());
            partyInfos.add(partyInfo);
        }

        respPartyInfo.setList(partyInfos);
        MessagePusher.pushMessage(role, respPartyInfo);
    }

    /**获得按等级降序的帮派列表*/
    public List<Party> getSortedParties(){
        ArrayList<Party> partyList = new ArrayList<>(PartyDataPool.partyMap.values());
        partyList.sort(Comparator.comparing(Party::getLevel).reversed());
        return partyList;
    }

    /**
     * 帮派等级取帮派最大人数
     */
    public int getPartyMaxMembers(int level) {
        int maxMembers = 0;
        if (level == 1) {
            maxMembers = 100;
        } else if (level == 2) {
            maxMembers = 150;
        } else if (level == 3) {
            maxMembers = 200;
        } else if (level == 4) {
            maxMembers = 300;
        }
        return maxMembers;
    }

    /**
     * 申请加入帮派
     * @param role
     * @param partyName
     */
    public void reqJoinParty(Role role, String partyName) {
        if (role == null || StringUtils.isEmpty(partyName)) {
            return ;
        }
        Party party = getPartyByName(partyName);
        if (party == null) {
            return ;
        }

        /**已经有帮派*/
        if (isHaveParty(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_304);
            return ;
        }

        /**是否有GM权限*/
        Account account = SpringUtils.getAccountService().getAccount(role.getSid());
        boolean isGm = account.getPrivilege() == 1000;

        /**帮派是否已经满员(gm权限跳过满员检测)*/
        if (isGm == false && isPartyFull(party)) {
            MessagePusher.notify2Player(role, I18nId.PMT_305);
            return ;
        }

        //     /**判断是否可以自动加入(gm权限自动加入)*///&& role.getLevel() <= party.getAutoAgreeMaxLevel()
        if (isGm || (party.isAutoAgreeWork() && role.getLevel()>= party.getAutoAgreeMinLevel() && (int)(role.getTaoPoint()/Const.ONE_YEAR_POINT) >= party.getAutoAgreeMinTao() )) {
            /**增加帮派成员*/
            String job = Const.PARTY_JOB_BANG_ZHONG + ":" + getPartyTotalCount(party);
            addPartyMember(party, new RoleView(role), job);

            dojoinParty(party, role);
            roleService.sendExtraAttribute(role);

            /**通知*/
            String acceptContent = I18nIdDataPool.getI18nContent(I18nId.PMT_316, party.getPartyName());
            MessagePusher.pushMessage(role, new RespNotifyMisc(acceptContent));

            /**帮派聊天消息*/
            String content = I18nIdDataPool.getI18nContent(I18nId.PMT_315, role.getName());
            npcPartyChat(party, content);

            /**帮派日志*/
            addPartyLog(party, I18nId.PMT_349, new String[]{role.getName()});

            notifyicon(role);
            newNpcService.closeDlg(role, "JoinPartyDlg");
            newNpcService.openDlg(role, "PartyInfoTabDlg");

            refresh( party);

        } else {
            ReqJoinMember reqJoinMember = new ReqJoinMember(role.getName(), role.getTao(),
                    roleService.getFamilyName(role.getPolar()), role.getCurrTitle(),
                    role.getGid(), Math.toIntExact(System.currentTimeMillis() / 1000),
                    role.getLevel(), role.getPolar(), role.getGender(),Long.parseLong(role.getfight_cap()+""));

            party.getReqJoin().put(role.getName(), reqJoinMember);

            MessagePusher.pushMessage(role,new RespNotifyMiscEx("你已向该帮派发出申请，请耐心等待！"));

            /**通知在线的管理人员*/
            notifyOnlineManager(party, new RespPartyNotification(Const.NOTIFICATION_PARTY_REQUEST));
        }
    }
    public void refresh(Party party) {
        Collection<PartyMemberObject> members = party.getMembers().values();
        if (members != null) {
            for (PartyMemberObject member : members) {
                Role role1 = roleService.getPlayerBy(member.getRoleUid());
                RespOpenPatry respOpenPatry = getRespOpenPatry(party);
                MessagePusher.pushMessage(role1, respOpenPatry);
            }
        }
    }
    /**帮派是否已经满员*/
    private boolean isPartyFull(Party party) {
        short partyTotalCount = getPartyTotalCount(party);
        int partyMaxCount = getPartyMaxMembers(party.getLevel());
        return partyTotalCount >= partyMaxCount;
    }


    /**
     * 一键加入帮派
     * @param role
     */
    public synchronized void oneKeyJoin(Role role) {
        if (role == null) {return ;}
        if (isHaveParty(role)) {return ;}

        /**先查找自动审批帮派，如果符合加入条件，则直接加入*/
        /**自动审批帮派没有符合条件的，则向所有帮派发送申请*/
        boolean joined = false;
        List<Party> sortedParties = getSortedParties();
        for (Party party : sortedParties) {
            /**满员则不处理*/
            if (isPartyFull(party)) {continue;}

            joined = autoJoin(role, party);
            if (joined) {break;}
        }

        if (joined == false) {
            for (Party party : sortedParties) {
                /**满员则不处理*/
                if (isPartyFull(party)) {continue;}

                /**加入申请列表*/
                ReqJoinMember reqJoinMember = new ReqJoinMember(role.getName(), role.getTao(),
                        roleService.getFamilyName(role.getPolar()), role.getCurrTitle(),
                        role.getGid(), Math.toIntExact(System.currentTimeMillis() / 1000),
                        role.getLevel(), role.getPolar(), role.getGender(),Long.parseLong(role.getfight_cap()+""));

                party.getReqJoin().put(role.getName(), reqJoinMember);


                /**通知在线的管理人员*/
                notifyOnlineManager(party, new RespPartyNotification(Const.NOTIFICATION_PARTY_REQUEST));
            }
        }
    }

    /**通知在线的管理人员*/
    private void notifyOnlineManager(Party party, Message message) {
        if (party == null || message == null) {return ;}

        Collection<Object> values = party.getJobs().values();
        for (Object uidObj : values) {
            long uid = (Long)uidObj;
            Role role = SpringUtils.getRoleService().getOnlinePlayer(uid);
            if (role == null) {continue;}

            MessagePusher.pushMessage(role, message);
        }
    }

    /**自动加入成功*/
    private boolean autoJoin(Role role, Party party) {
        if (role == null || party == null) {return false;}

        if (party.isAutoAgreeWork() && role.getLevel()>= party.getAutoAgreeMinLevel() && role.getLevel() <= party.getAutoAgreeMaxLevel()) {
            /**增加帮派成员*/
            String job = Const.PARTY_JOB_BANG_ZHONG + ":" + getPartyTotalCount(party);
            addPartyMember(party, new RoleView(role), job);

            dojoinParty(party, role);
            roleService.sendExtraAttribute(role);

            /**通知*/
            String acceptContent = I18nIdDataPool.getI18nContent(I18nId.PMT_316, party.getPartyName());
            MessagePusher.pushMessage(role, new RespNotifyMisc(acceptContent));

            /**帮派聊天消息*/
            String content = I18nIdDataPool.getI18nContent(I18nId.PMT_315, role.getName());
            npcPartyChat(party, content);

            String mailTitle = I18nIdDataPool.getI18nContent(I18nId.PMT_317);
            String mailContent = I18nIdDataPool.getI18nContent(I18nId.PMT_318, party.getPartyName(), party.getPartyName());
            Mail mail = SpringUtils.getMailService().createMail(mailTitle, mailContent, 1 * TimeUtil.ONE_HOUR);
            SpringUtils.getMailService().sendNewMail(role, mail);

            /**帮派日志*/
            addPartyLog(party, I18nId.PMT_349, new String[]{role.getName()});

            return true;
        }

        return false;
    }

    /**
     * 查看申请列表
     * @param role
     */
    public synchronized void checkJoinList(Role role) {
        if (role == null) {return ;}

        Party party = getParty(role);
        if (party == null) {
            return ;
        }

        NutMap reqJoin = party.getReqJoin();
        for (Map.Entry<String, Object> entry : reqJoin.entrySet()) {
            ArrayList<JoinMemberInfo> JoinMemberInfos = new ArrayList<>();
            RespJoinPartyList respJoinPartyList = new RespJoinPartyList();
            respJoinPartyList.setList(JoinMemberInfos);
            respJoinPartyList.setName(entry.getKey());
            ReqJoinMember reqJoinMember = (ReqJoinMember) entry.getValue();
            JoinMemberInfos.add(reqJoinMember.asJoinMemberInfo());
            MessagePusher.pushMessage(role, respJoinPartyList);
        }

        MessagePusher.pushMessage(role, new RespJoinPartyList());
    }

    /**
     * 同意入帮
     * @param role
     * @param name
     */
    public void agreeJoinParty(Role role, String name) {
        if (role == null || StringUtils.isEmpty(name)) {return ;}

        Party party = getParty(role.getPartyId());
        if (party == null) {
            return ;
        }

        /**判断是否有权限*/
        if (!isAgreeOrDenyApply(role)) {
            return ;
        }

        ArrayList<String> names = new ArrayList<>();
        if (name.equals("all\t")) {
            /**同意全部*/
            Set<String> keySet = party.getReqJoin().keySet();
            if (keySet != null) {
                names.addAll(keySet);
            }
        } else {
            names.add(name);
        }

        RespClearnRequest respClearnRequest = new RespClearnRequest();
        respClearnRequest.setType("party");
        respClearnRequest.setNames(names);
        MessagePusher.pushMessage(role, respClearnRequest);

        for (String tempName : names) {
            /**移除申请记录*/
            ReqJoinMember reqJoinMember = (ReqJoinMember)party.getReqJoin().remove(tempName);
            if (reqJoinMember == null) {continue;}

            long reqUid = Long.parseLong(reqJoinMember.getGid());
            RoleView reqRoleView = new RoleView(reqUid);

            /**申请人已经加入到其他帮派*/
            if (isHaveParty(reqRoleView.getPartyName())) {
                MessagePusher.notify2Player(role, I18nId.PMT_306);
                continue;
            }
            /**离线时已经加入到其他帮派*/
            if (!reqRoleView.isOnline() && PartyDataPool.offlineRoleParty.getOrDefault(reqUid, 0L) > 0) {
                MessagePusher.notify2Player(role, I18nId.PMT_306);
                continue;
            }

            /**增加帮派成员*/
            String job = Const.PARTY_JOB_BANG_ZHONG + ":" + getPartyTotalCount(party);
            addPartyMember(party, reqRoleView, job);


            Role reqRole = reqRoleView.getRole();
            if (reqRole != null) {
                ThreadLocalUtil.addLocalTask(reqRole, () -> joinParty(party, reqRole));
            } else {
                /**离线时保存新的帮派id到PlayerProfile中，离线玩家登录时进行加帮的操作*/
                PartyDataPool.offlineRoleParty.put(reqUid, party.getId());
            }

            /**帮派聊天消息*/
            String content = I18nIdDataPool.getI18nContent(I18nId.PMT_315, reqRoleView.getName());
            npcPartyChat(party, content);

            checkPartyMember(role, (short) 1, "", "");

            /**帮派日志*/
            String partyJob = getPartyJob(role);
            addPartyLog(party, I18nId.PMT_350, new String[]{partyJob, role.getName(), reqRoleView.getName()});
        }
    }

    /**是否有同意或者拒绝申请权限*/
    private boolean isAgreeOrDenyApply(Role role) {
        byte permission = getPermission(role);
        return permission == Const.PARTY_PERMISSION_BZ || permission == Const.PARTY_PERMISSION_FBZ
                || permission == Const.PARTY_PERMISSION_ZL || permission == Const.PARTY_PERMISSION_HF
                || permission == Const.PARTY_PERMISSION_TZ
                ;
    }

    private void joinParty(Party party, Role role) {
        dojoinParty(party, role);
        roleService.sendExtraAttribute(role);

        /**通知被操作人*/
        String acceptContent = I18nIdDataPool.getI18nContent(I18nId.PMT_316, party.getPartyName());
        MessagePusher.pushMessage(role, new RespNotifyMisc(acceptContent));

        /**邮件消息*/
        String mailTitle = I18nIdDataPool.getI18nContent(I18nId.PMT_317);
        String mailContent = I18nIdDataPool.getI18nContent(I18nId.PMT_318, party.getPartyName(), party.getPartyName());
        Mail mail = SpringUtils.getMailService().createMail(mailTitle, mailContent, 1 * TimeUtil.ONE_HOUR);
        SpringUtils.getMailService().sendNewMail(role, mail);
    }

    /**角色加入帮派*/
    private void dojoinParty(Party party, Role role) {
        if (party == null || role == null) {return ;}

        role.setPartyId(party.getId());

        PartyMemberObject partyMember = getPartyMember(party, role);

        /**上一帮派帮贡*/
        int prevContrib = getPrevContrib(role);
        if (prevContrib > 0) {
            /**加入与上一帮派不同时，则恢复一半的帮贡，或者恢复全部*/
            if (role.getPrevPartyId() != party.getId()) {
                partyMember.setContrib(prevContrib / 2);
            } else {
                partyMember.setContrib(prevContrib);
            }
            party.save();
        }

        addPartyTitle(party, role);

        role.setPrevPartyId(0);
        role.save();
    }

    /**获得上一帮贡*/
    private int getPrevContrib(Role role) {
        if (role == null) {return 0;}
        if (role.getPrevPartyId() <= 0) {return 0;}
        Party prevParty = getParty(role.getPrevPartyId());

        PrevPartyMemberObject prevPartyMember = prevParty.getPrevMembers().get(role.getUid());
        if (prevPartyMember == null) {
            return 0;
        }

        return prevPartyMember.getContrib();
    }

    /**获得帮贡*/
    public int getContrib(Role role) {
        Party party = getParty(role);
        if (party == null) {return 0;}
        PartyMemberObject partyMember = getPartyMember(party, role);
        return partyMember != null ? partyMember.getContrib() : 0;
    }

    /**增加帮派称号*/
    public void addPartyTitle(Party party, Role role) {
        PartyMemberObject partyMember = getPartyMember(party, role);
        if (partyMember == null) {return ;}

        String partyJobName = getPartyJobName(partyMember);
        if (partyJobName != null) {
            roleService.addTitle(role, new TitleInfo(Const.TITLE_TYPE_PARTY, party.getPartyName() + partyJobName));
        }
    }

    /**删除帮派称号*/
    private void delPartyTitle(Role role) {
        roleService.delTitle(role, Const.TITLE_TYPE_PARTY);
    }

    /**获得玩家对应的帮派成员对象*/
    public PartyMemberObject getPartyMember(Party party, Role role) {
        if (party == null || role == null) {return null;}

        return party.getMembers().get(role.getUid());
    }

    /**获得玩家对应的帮派成员对象*/
    public PartyMemberObject getPartyMember(Party party, long uid) {
        if (party == null) {return null;}

        return party.getMembers().get(uid);
    }

    /**通过帮派成员对象获得帮派职业*/
    private String getPartyJobName(PartyMemberObject partyMember) {
        if (partyMember == null) {return null;}

        if (partyMember.getJob() != null) {
            return partyMember.getJob().split(":")[0].trim();
        }

        return null;
    }


    /**
     * 查看帮派成员
     * @param role
     */
    public synchronized void checkPartyMember(Role role, short page, String roleName, String sid) {
        if (role == null) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        RespOpenPatry respOpenPatry = getRespOpenPatry(party);
        MessagePusher.pushMessage(role, respOpenPatry);
        RespPartyMembers respPartyMembers = getRespPartyMembers(party);
        MessagePusher.pushMessage(role, respPartyMembers);
    }

    public RespPartyMembers getRespPartyMembers(Party party) {
        RespPartyMembers respPartyMembers = new RespPartyMembers();
        List<PartyMember> members = getSiderInfos(party);
        respPartyMembers.setList(members);
        return respPartyMembers;
    }

    private List<PartyMember> getSiderInfos(Party party) {
        List<PartyMember> partyMembers = new ArrayList<>();
        Collection<PartyMemberObject> members = party.getMembers().values();
        if (members != null) {
            short olineStatus=0;
            for (PartyMemberObject member : members) {
                PartyMember partyMember = new PartyMember();
                partyMember.setRoleName(member.getRoleName());
                partyMember.setJob(member.getJob());
                partyMember.setLastOnlineTime(member.getLastOnlineTime());
                partyMember.setJoinTime(member.getJoinTime());
                partyMember.setPolor(member.getPolor());
                partyMember.setTao(member.getTao());
                partyMember.setGid(member.getGid());
                partyMember.setLevel(member.getLevel());
                olineStatus = (short) (roleService.isOnline(member.getRoleUid()) ? 1 : 0);
                partyMember.setOlineStatus(olineStatus);
                partyMember.setFamily(member.getFamily());
                partyMember.setVitality(member.getVitality());
                partyMember.setCurrWeekVitality(member.getCurrWeekVitality());
                partyMember.setLastWeekVitality(member.getLastWeekVitality());

                partyMembers.add(partyMember);
            }
        }

        return partyMembers;
    }

    /**
     * 拒绝入帮
     * @param role
     * @param name
     */
    public void refuseJoinParty(Role role, String name) {
        if (role == null || StringUtils.isEmpty(name)) {return ;}

        Party party = getParty(role.getPartyId());
        if (party == null) {
            return ;
        }

        /**判断是否有权限*/
        if (!isAgreeOrDenyApply(role)) {
            return ;
        }

        ArrayList<String> names = new ArrayList<>();
        if (name.equals("all\t")) {
            /**拒绝全部*/
            Set<String> keySet = party.getReqJoin().keySet();
            if (keySet != null) {
                names.addAll(keySet);
            }
        } else {
            names.add(name);
        }

        /**移除申请记录*/
        RespClearnRequest respClearnRequest = new RespClearnRequest();
        respClearnRequest.setType("party");
        respClearnRequest.setNames(names);
        MessagePusher.pushMessage(role, respClearnRequest);

        for (String tempName : names) {
            ReqJoinMember reqJoinMember = (ReqJoinMember)party.getReqJoin().remove(tempName);
            long reqUid = Long.parseLong(reqJoinMember.getGid());

            Role sessionRole = SpringUtils.getRoleService().getOnlinePlayer(reqUid);
            MessagePusher.notify2Player(sessionRole, I18nId.PMT_307);
        }
    }

    /**
     * 查看指定帮派简要信息
     * @param role
     * @param partyName
     * @param partyId
     * @param type
     */
    public synchronized void checkPartyInfo(Role role, String partyName, String partyId, String type) {
        if (role == null) {
            return ;
        }

        Party party = getParty(Long.parseLong(partyId));
        if (party == null) {
            return;
        }

        RespCheckPartyInfo respCheckPartyInfo = new RespCheckPartyInfo();
        respCheckPartyInfo.setPartyName(party.getPartyName());
        respCheckPartyInfo.setPartyId(String.valueOf(party.getId()));
        respCheckPartyInfo.setCreator(party.getCreater());
        respCheckPartyInfo.setPartyIcon(party.getIcon());
        respCheckPartyInfo.setConstruct(party.getJianshe());
        respCheckPartyInfo.setCreateTime(Math.toIntExact(party.getCreateTime() / TimeUtil.ONE_SECOND));
        respCheckPartyInfo.setLevel(party.getLevel());
        respCheckPartyInfo.setPopulation(getPartyTotalCount(party));
        respCheckPartyInfo.setMoney(party.getCapital());
        respCheckPartyInfo.setMemberInfos(getPartyMemberInfos(party));
        respCheckPartyInfo.setSkillInfoList(getPartySkillInfos(party));
        respCheckPartyInfo.setNotice(party.getNotice());

        MessagePusher.pushMessage(role, respCheckPartyInfo);
    }

    private List<PartyMemberInfo> getPartyMemberInfos(Party party) {
        List<PartyMemberInfo> memberInfos = new ArrayList<>();

        for (String jobName : Const.MANAGER_JOBS) {
            PartyMemberInfo partyMemberInfo = new PartyMemberInfo();
            partyMemberInfo.setPartyTitle(jobName);

            Long uid = party.getJobs().getLong(jobName);
            String name = "暂无";
            if (uid != null) {
                PartyMemberObject partyMemberObject = party.getMembers().get(uid);
                if (partyMemberObject != null) {
                    name = partyMemberObject.getRoleName();
                }
            }
            partyMemberInfo.setName(name);
            partyMemberInfo.setGid(String.valueOf(uid));
            memberInfos.add(partyMemberInfo);
        }

        return memberInfos;
    }

    private List<PartySkillInfo> getPartySkillInfos(Party party) {
        List<PartySkillInfo> skillInfoList = new ArrayList<>();
        for (NutMap nutMap : party.getSkills()) {
            PartySkillInfo partySkillInfo = new PartySkillInfo();
            partySkillInfo.setSkillLevel((short) nutMap.getInt("skillLevel"));
            partySkillInfo.setSkillName(nutMap.getString("skillName"));
            partySkillInfo.setCurrJindu(nutMap.getInt("currJindu"));
            partySkillInfo.setSkillId((short) nutMap.getInt("skillId"));
            partySkillInfo.setTotal(nutMap.getInt("total"));
            skillInfoList.add(partySkillInfo);
        }

        return skillInfoList;
    }

    /**
     * 升级帮派
     * @param role
     */
    public void upgrade(Role role) {
        Party party = getParty(role.getPartyId());
        if (party == null) {
            return ;
        }

        /**不是帮主*/
        if (!isPartyLeader(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_340, "升级");
            return ;
        }

        short nextLevel = (short) (party.getLevel() + 1);
        Integer construction = PartyDataPool.partyUpgrades.get(nextLevel);
        if (construction == null) {
            MessagePusher.notify2Player(role, I18nId.PMT_372);
            return ;
        }

        /**建设度*/
        if (party.getJianshe() < construction) {
            MessagePusher.notify2Player(role, I18nId.PMT_373, construction);
            return;
        }

        /**扣除建设度*/
        substractConstruction(role, construction);

        party.setLevel(nextLevel);
        party.save();
        openPartyDlg(role);
        newNpcService.closeDlg(role, "PartyInfoTabDlg");
        newNpcService.openDlg(role, "PartyInfoTabDlg");
    }

    /**
     * 修改帮派公告
     * @param role
     * @param notice
     */
    public synchronized void modifyNotice(Role role, String notice) {
        Party party = getParty(role.getPartyId());
        if (party == null) {
            return ;
        }

        /**不是帮主*/
        if (!isPartyLeader(role)) {
            return ;
        }

        /**内容长度过长*/
        if (notice.length() > 2048) {
            MessagePusher.notify2Player(role, I18nId.PMT_362);
            return ;
        }

        List<String> set = wordService.checkDirtyWords(notice);
        if (set.size() >= 1) { //敏感词检测
            MessagePusher.pushMessage(role,new RespMsg("输入的内容存在敏感词。"));
            return;
        }

        party.setNotice(notice);

        party.save();

        /**提示成功*/
        MessagePusher.notify2Player(role, I18nId.PMT_358);
    }

    /**
     * 开除
     * @param role
     * @param uid
     * @param name
     */
    public synchronized void kickOut(Role role, long uid, String name) {
        if (role == null) {return ;}
        /**判断是否是自己，不能开除自己*/
        if (role.getUid() == uid) {
            return ;
        }

        Party party = getParty(role.getPartyId());
        if (party == null) {return ;}
        /**判断目标角色是否在对应帮派*/
        if (!isInParty(party, uid)) {
            MessagePusher.notify2Player(role, I18nId.PMT_308);
            return ;
        }

        /**判断是否有对应权限*/
        if (!isKickPermission(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_309);
            return ;
        }

        /**判断对方是否权限更高*/
        if (isPermissionHigher(party, uid, role.getUid())) {
            MessagePusher.notify2Player(role, I18nId.PMT_310);
            return ;
        }

        /**执行开除操作*/
        doKickOut(role, party, uid);
        refresh( party);
    }

    /**前者帮派权限是否高于后者*/
    private boolean isPermissionHigher(Role firstRole, Role secondRole) {
        byte firstPermission = getPermission(firstRole);
        byte secondPermission = getPermission(secondRole);

        /**值越小，权限越高*/
        return firstPermission < secondPermission;
    }

    private boolean isPermissionHigher(Party party, long firstUid, long secondUid) {
        PartyMemberObject firstPartyMember = party.getMembers().get(firstUid);
        PartyMemberObject secondPartyMember = party.getMembers().get(secondUid);

        byte firstPermission = getPermission(firstPartyMember);
        byte secondPermission = getPermission(secondPartyMember);

        /**值越小，权限越高*/
        return firstPermission < secondPermission;
    }

    /**是否有踢除权限*/
    private boolean isKickPermission(Role role) {
        if (role == null)  {return false;}

        byte permission = getPermission(role);
        return permission == Const.PARTY_PERMISSION_BZ || permission == Const.PARTY_PERMISSION_FBZ;
    }

    /**
     * 获得角色对应的帮派权限
     * @param role
     * @return
     */
    private byte getPermission(Role role) {
        String partyJob = getPartyJob(role);
        if (partyJob != null) {
            Byte permission = PartyDataPool.partyPermissions.get(partyJob);
            if (permission != null) {return permission;}
        }

        /**找不到时，默认帮众权限*/
        return Const.PARTY_PERMISSION_BZONG;
    }

    /**获得角色对应的帮派职业*/
    public String getPartyJob(Role role) {
        Party party = getParty(role);
        if (party == null) {return null;}
        PartyMemberObject partyMember = getPartyMember(party, role);
        return getPartyJobName(partyMember);
    }

    /**获得角色对应的帮派职业*/
    public String getPartyJob(Party party, long uid) {
        if (party == null) {return null;}
        PartyMemberObject partyMember = getPartyMember(party, uid);
        return getPartyJobName(partyMember);
    }

    private byte getPermission(PartyMemberObject partyMember) {
        String partyJob = partyMember.getJob();
        if (partyJob != null) {
            Byte permission = PartyDataPool.partyPermissions.get(partyJob);
            if (permission != null) {return permission;}
        }

        /**找不到时，默认帮众权限*/
        return Const.PARTY_PERMISSION_BZONG;
    }

    /**执行开除操作*/
    private void doKickOut(Role role, Party party, long uid) {
        if (party == null) {return ;}
        RoleView roleView = new RoleView(uid);

        log.info("{}({})把{}({})从帮派{}({})开除", role.getUid(), role.getName(), roleView.getUid(), roleView.getName(), party.getId(), party.getPartyName());

        /**帮派聊天消息*/
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_314, getPartyJob(role), role.getName(), roleView.getName());
        npcPartyChat(party, content);

        Role targetRole = roleView.getRole();

        /**在线给到玩家线程处理*/
        if (targetRole != null) {
            ThreadLocalUtil.addLocalTask(targetRole, () -> leaveParty(party, targetRole));
        } else {
            PartyDataPool.offlineRoleParty.put(uid, -1L);
        }

        /**从帮派成员列表删除*/
        PartyMemberObject partyMember = party.getMembers().remove(uid);
        party.save();

        String targetPartyJob = getPartyJobName(partyMember);
        party.getJobs().remove(targetPartyJob);
        if (roleView.getName().equals(party.getHeir())) {
            party.setHeir(null);
            party.setHeirEndTime(0);
        }

        /**通知操作人*/
        MessagePusher.notify2Player(role, I18nId.PMT_311, roleView.getName());

        RespOpenPatry respOpenPatry = getRespOpenPatry(party);
        MessagePusher.pushMessage(role, respOpenPatry);
        RespPartyMembers respPartyMembers = getRespPartyMembers(party);
        MessagePusher.pushMessage(role, respPartyMembers);

        /**帮派日志*/
        String partyJob = getPartyJob(role);
        addPartyLog(party, I18nId.PMT_351, new String[]{partyJob, role.getName(), roleView.getName()});
    }

    private void leaveParty(Party party, Role role) {
        doLeaveParty(role);

        /**离开帮派地图*/
        if (isInPartyMap(role)) {
            leavePartyMap(role);
        }

        /**通知被操作人*/
        String kickContent = I18nIdDataPool.getI18nContent(I18nId.PMT_313, party.getPartyName());
        MessagePusher.pushMessage(role, new RespNotifyMisc(kickContent));

        /**邮件消息*/
        String mailTitle = I18nIdDataPool.getI18nContent(I18nId.PMT_312);
        String mailContent = I18nIdDataPool.getI18nContent(I18nId.PMT_313, party.getPartyName());
        Mail mail = SpringUtils.getMailService().createMail(mailTitle, mailContent, 1 * TimeUtil.ONE_DAY);
        SpringUtils.getMailService().sendNewMail(role, mail);
    }

    public void doLeaveParty(Role role) {
        /**删除发的帮派红包*/
        redBagHandler.delPartyRedBag(role);

        role.setPrevPartyId(role.getPartyId());
        role.setPartyId(0);
        role.save();
        roleService.sendExtraAttribute(role);

        delPartyTitle(role);
    }

    /**帮派使者发帮派消息*/
    private void npcPartyChat(Party party, String content) {
        if (party == null || StringUtils.isEmpty(content)) {return ;}

        NPC npc = SpringUtils.getMapService().getNpc(Const.PARTY_EMISSARY_NPCID);
        RespChat partyRespChat = getPartyRespChat(npc.getId(), npc.getName(), (short) npc.getIcon(), party.getPartyName(), content);
        SenderUtils.pushPartyChatMessage(party.getId(), partyRespChat);
    }

    private RespChat getPartyRespChat(int id, String name, short icon, String partyName, String content) {
        RespChat respChat = new RespChat();
        respChat.setMsg(content);
        ArrayList<FiedValue> list = new ArrayList<>();
        list.add(new FiedValue(3024, ""));
        list.add(new FiedValue(305, ""));
        list.add(new FiedValue(445, 0));
        list.add(new FiedValue(31, 0));
        list.add(new FiedValue(40, icon));
        list.add(new FiedValue(3023, ""));
        respChat.setList(list);
        respChat.setRoleName(name);
        respChat.setLineName(SpringUtils.getBean(ServerService.class).getServer().getSonName());
        respChat.setRoleId(id);
        respChat.setTime((int) (System.currentTimeMillis() / TimeUtil.ONE_SECOND));
        respChat.setType(ChatConst.PARTY);
        respChat.setPartyName(partyName);

        return respChat;
    }

    /**设置自动接受配置*/
    public synchronized void setAutoAgreeSetting(Role role, short minLevel, short maxLevel, byte isWork, byte isChange,int tao) {
        if (role == null) {return ;}
        Party party = getParty(role.getPartyId());
        /**还没有帮派*/
        if (party == null) {
            MessagePusher.notify2Player(role, I18nId.PMT_319);
            return ;
        }
        /**没有权限*/
        if (!isAgreeOrDenyApply(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_345);
            return ;
        }

        if (isChange == 0) {
            party.setAutoAgreeMinLevel(minLevel);
            party.setAutoAgreeMaxLevel(maxLevel);
            party.setAutoAgreeMinTao(tao);
        } else {
            party.setAutoAgreeWork(isWork == 1 ? true : false);
        }
        party.save();

        openPartyDlg(role);

        if (party.isAutoAgreeWork()) {
            addPartyLog(party, I18nId.PMT_359, new String[]{role.getName(), String.valueOf(minLevel), String.valueOf(maxLevel)});
        } else {
            addPartyLog(party, I18nId.PMT_360, new String[]{role.getName()});
        }
    }

    /**
     * 退出帮派
     * @param role
     */
    public synchronized void quitParty(Role role) {
        if (role == null) {return ;}
        Party party = getParty(role.getPartyId());
        if (party == null) {
            MessagePusher.notify2Player(role, I18nId.PMT_319);
            return ;
        }

        /**帮主不能退出帮派*/
        String partyJob = getPartyJob(role);
        if (Const.PARTY_JOB_BANG_ZHU.equals(partyJob)) {
            MessagePusher.notify2Player(role, I18nId.PMT_320, partyJob);
            return ;
        }

        /**帮派聊天消息*/
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_322, role.getName());
        npcPartyChat(party, content);

        doLeaveParty(role);

        /**从帮派成员列表删除*/
        party.getMembers().remove(role.getUid());
        party.save();

        party.getJobs().remove(partyJob);
        if (role.getName().equals(party.getHeir())) {
            party.setHeir(null);
            party.setHeirEndTime(0);
        }

        /**离开帮派地图*/
        if (isInPartyMap(role)) {
            leavePartyMap(role);
        }

        MessagePusher.notify2Player(role, I18nId.PMT_321, party.getPartyName());

        RespOpenPatry respOpenPatry = getRespOpenPatry(party);
        MessagePusher.pushMessage(role, respOpenPatry);
        RespPartyMembers respPartyMembers = getRespPartyMembers(party);
        MessagePusher.pushMessage(role, respPartyMembers);

        /**帮派日志*/
        if (isManager(partyJob)) {
            addPartyLog(party, I18nId.PMT_354, new String[]{role.getName(), role.getName()});
        } else {
            addPartyLog(party, I18nId.PMT_352, new String[]{role.getName()});
        }
    }

    /**是否在帮派地图*/
    public boolean isInPartyMap(Role role) {
        if (role == null) {return false;}
        return role.getPos().getMapId() == Const.PARTY_MAPID;
    }

    /**离开帮派地图*/
    public void leavePartyMap(Role role) {
        ReqTelePort reqTelePort = new ReqTelePort();
        reqTelePort.setMapId(Const.PARTY_EXIT_MAPID);
        reqTelePort.setX(Const.PARTY_EXIT_X);
        reqTelePort.setY(Const.PARTY_EXIT_Y);
        SpringUtils.getMapService().changeMap(role, reqTelePort);
    }

    /**登录时处理*/
    public void handleLogin(Role role) {
        Party party = getParty(role.getPartyId());
        Long newPartyId = PartyDataPool.offlineRoleParty.remove(role.getUid());
        if (party != null) {
            if (newPartyId != null && newPartyId == -1) {
                leaveParty(party, role);
            } else {
                /**称号修改时*/
                PartyMemberObject partyMember = party.getMembers().get(role.getUid());
                if (partyMember != null && partyMember.isTitleChange()) {
                    partyMember.setTitleChange(false);
                    party.save();

                    String jobName = partyMember.getJob();
                    roleService.changeTitle(role, new TitleInfo(Const.TITLE_TYPE_PARTY, getTitle(party.getPartyName(), jobName)));
                }

                /**申请列表*/
                if (isAgreeOrDenyApply(role) && isHaveJoinRequest(party)) {
                    RespPartyNotification respPartyNotification = new RespPartyNotification(Const.NOTIFICATION_PARTY_REQUEST);
                    MessagePusher.pushMessage(role, respPartyNotification);
                }
            }
        } else {
            /**没有帮派时，却在帮派地图, 需要离开帮派地图*/
            /**处理离线时被开除情况*/
            if (isInPartyMap(role)) {
                leavePartyMap(role);
            }

            /**离线时被同意加入帮派*/
            if (newPartyId != null && newPartyId > 0) {
                party = getParty(newPartyId);

                joinParty(party, role);
            }
        }
    }

    /**登出时处理*/
    public void handleLogout(Role role) {
        Party party = getParty(role);
        if (party == null) {return ;}

        PartyMemberObject partyMember = getPartyMember(party, role);
        if (partyMember == null) {return ;}
        long now = System.currentTimeMillis();
        partyMember.setLastOnlineTime((int) (now / TimeUtil.ONE_SECOND));
    }

    /**角色改名处理*/
    public void handleRoleNameChange(Role role, String prevName, String currName) {
        Party party = getParty(role);
        if (party == null) {return ;}

        PartyMemberObject partyMember = getPartyMember(party, role);

        /**成员*/
        partyMember.setRoleName(currName);

        /**继承人*/
        if (prevName.equals(party.getHeir())) {
            party.setHeir(currName);
        }

        party.save();
    }

    /**禁言*/
    public synchronized void prohibitSpeaking(Role role, long uid, String name, short hours) {
        if (role == null) {return ;}

        /**判断是否是自己，不能禁言自己*/
        if (role.getUid() == uid) {
            return ;
        }

        Party party = getParty(role.getPartyId());
        if (party == null) {return ;}

        /**判断目标角色是否在对应帮派*/
        if (!isInParty(party, uid)) {
            MessagePusher.notify2Player(role, I18nId.PMT_308);
            return ;
        }

        /**判断是否有权限*/
        if (!isDenyPermission(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_335);
            return ;
        }
        /**判断对方是否权限更高*/
        if (isPermissionHigher(party, uid, role.getUid())) {
            MessagePusher.notify2Player(role, I18nId.PMT_336);
            return ;
        }

        int endtime = (int) ((System.currentTimeMillis() + hours * TimeUtil.ONE_HOUR) / TimeUtil.ONE_SECOND);
        PartyDeny partyDeny = new PartyDeny(String.valueOf(uid), endtime);
        party.getDenyMap().put(uid, partyDeny);
        party.save();

        sendDenyList(role);

        /**帮派聊天消息*/
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_337, name, hours);
        npcPartyChat(party, content);

        /**邮件消息*/
        Role targetRole = SpringUtils.getRoleService().getOnlinePlayer(uid);
        if (targetRole != null) {
            String mailTitle = I18nIdDataPool.getI18nContent(I18nId.PMT_338);
            String mailContent = I18nIdDataPool.getI18nContent(I18nId.PMT_339, hours, hours);
            Mail mail = SpringUtils.getMailService().createMail(mailTitle, mailContent, 1 * TimeUtil.ONE_DAY);
            SpringUtils.getMailService().sendNewMail(targetRole, mail);
        }
    }

    /**是否有禁言权限*/
    private boolean isDenyPermission(Role role) {
        byte permission = getPermission(role);
        return permission == Const.PARTY_PERMISSION_BZ || permission == Const.PARTY_PERMISSION_FBZ;
    }

    /**任命*/
    public synchronized void changeJob(Role role, long uid, String name, short jobId) {
        if (role == null) {return ;}
        /**判断是否是自己，不能任命自己*/
        if (role.getUid() == uid) {
            return ;
        }

        Party party = getParty(role.getPartyId());
        if (party == null) {return ;}

        /**判断目标角色是否在对应帮派*/
        if (!isInParty(party, uid)) {
            MessagePusher.notify2Player(role, I18nId.PMT_308);
            return ;
        }

        /**判断是否有权限*/
        if (!isChangeJobPermission(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_326);
            return ;
        }

        if (isPermissionHigher(party, uid, role.getUid())) {
            MessagePusher.notify2Player(role, I18nId.PMT_327);
            return ;
        }

        String jobName = PartyDataPool.jobId2Names.get(jobId);
        String oldJobName = getPartyJob(party, uid);

        party.getJobs().remove(oldJobName);
        party.getJobs().setv(jobName, uid);

        String job = jobName + ":" + getPartyTotalCount(party);
        PartyMemberObject partyMember = getPartyMember(party, uid);
        partyMember.setJob(job);
        party.save();

        RoleView roleView = new RoleView(uid);
        Role targetRole = roleView.getRole();

        if (targetRole != null) {
            roleService.changeTitle(targetRole,  new TitleInfo(Const.TITLE_TYPE_PARTY, getTitle(party.getPartyName(), jobName)));
        }

        roleService.sendExtraAttribute(role);

        RespOpenPatry respOpenPatry = getRespOpenPatry(party);
        MessagePusher.pushMessage(role, respOpenPatry);
        RespPartyMembers respPartyMembers = getRespPartyMembers(party);
        MessagePusher.pushMessage(role, respPartyMembers);

        /**帮派聊天消息*/
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_328, role.getName(), name, oldJobName, jobName);
        npcPartyChat(party, content);

        /**邮件消息*/
        if (targetRole != null) {
            String mailTitle = I18nIdDataPool.getI18nContent(I18nId.PMT_330);
            String mailContent = I18nIdDataPool.getI18nContent(I18nId.PMT_331, role.getName(), oldJobName, jobName);
            Mail mail = SpringUtils.getMailService().createMail(mailTitle, mailContent, 1 * TimeUtil.ONE_DAY);
            SpringUtils.getMailService().sendNewMail(targetRole, mail);
        }

        /**帮派日志*/
        String partyJob = getPartyJob(role);
        addPartyLog(party, I18nId.PMT_353, new String[]{partyJob, role.getName(), roleView.getName(), oldJobName, jobName});
    }

    /**是否有任职的权限*/
    private boolean isChangeJobPermission(Role role) {
        byte permission = getPermission(role);
        return permission == Const.PARTY_PERMISSION_BZ || permission == Const.PARTY_PERMISSION_FBZ;
    }

    /**
     * 传位
     * @param role
     * @param uid
     */
    public synchronized void demiseMember(Role role, long uid, String name) {
        if (role == null) {return ;}

        /**判断是否是自己，不能传位自己*/
        if (role.getUid() == uid) {
            return ;
        }
        Party party = getParty(role.getPartyId());
        if (party == null) {return ;}

        /**只有帮主才有权限传位*/
        if (!isPartyLeader(role)) {return ;}

        /** 不在当前帮派时，则不能传位*/
        if (!isInParty(party, uid)) { return ;}

        /**如果已经有继承人，则不能操作*/
        if (StringUtils.isNotEmpty(party.getHeir())) {return ;}

        party.setHeir(name);
        party.setHeirEndTime(System.currentTimeMillis() + Const.HEIR_DAY * TimeUtil.ONE_DAY);

        party.save();

        RespOpenPatry respOpenPatry = getRespOpenPatry(party);
        MessagePusher.pushMessage(role, respOpenPatry);
        RespPartyMembers respPartyMembers = getRespPartyMembers(party);
        MessagePusher.pushMessage(role, respPartyMembers);

        MessagePusher.notify2Player(role, I18nId.PMT_323, name);

        /**帮派聊天消息*/
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_324, role.getName(), name);
        npcPartyChat(party, content);

        /**邮件消息*/
        Role targetRole = SpringUtils.getRoleService().getOnlinePlayer(uid);
        if (targetRole != null) {
            String mailTitle = I18nIdDataPool.getI18nContent(I18nId.PMT_332);
            String mailContent = I18nIdDataPool.getI18nContent(I18nId.PMT_333, role.getName());
            Mail mail = SpringUtils.getMailService().createMail(mailTitle, mailContent, 1 * TimeUtil.ONE_DAY);
            SpringUtils.getMailService().sendNewMail(targetRole, mail);
        }

        /**帮派日志*/
        addPartyLog(party, I18nId.PMT_355, new String[]{role.getName(), targetRole.getName(), targetRole.getName()});
    }

    /**是否是帮主*/
    private boolean isPartyLeader(Role role) {
        String partyJob = getPartyJob(role);
        return Const.PARTY_JOB_BANG_ZHU.equals(partyJob);
    }

    /**roleUid是否在传入的帮派*/
    private boolean isInParty(Party party, long roleUid) {
        if (party == null) {return false;}

        return party.getMembers().containsKey(roleUid);
    }

    /**
     * 取消传位
     * @param role
     */
    public synchronized void cancelDemiseMember(Role role) {
        if (role == null) {return ;}

        Party party = getParty(role.getPartyId());
        if (party == null) {return ;}

        /**只有帮主才有权限传位*/
        if (!isPartyLeader(role)) {return ;}

        /**之前没有继承人，则不能操作*/
        if (StringUtils.isEmpty(party.getHeir())) {return ;}

        String oldHeir = party.getHeir();
        party.setHeir(null);
        party.setHeirEndTime(0);

        party.save();

        RespOpenPatry respOpenPatry = getRespOpenPatry(party);
        MessagePusher.pushMessage(role, respOpenPatry);
        RespPartyMembers respPartyMembers = getRespPartyMembers(party);
        MessagePusher.pushMessage(role, respPartyMembers);

        /**帮派聊天消息*/
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_325, role.getName(), oldHeir);
        npcPartyChat(party, content);

        /**邮件消息*/
        PartyMemberObject member = getMemberByName(party, oldHeir);
        if (member != null) {
            Role targetRole = SpringUtils.getRoleService().getOnlinePlayer(member.getRoleUid());
            if (targetRole != null) {
                String mailTitle = I18nIdDataPool.getI18nContent(I18nId.PMT_332);
                String mailContent = I18nIdDataPool.getI18nContent(I18nId.PMT_334, role.getName());
                Mail mail = SpringUtils.getMailService().createMail(mailTitle, mailContent, 1 * TimeUtil.ONE_DAY);
                SpringUtils.getMailService().sendNewMail(targetRole, mail);
            }
        }
    }

    /**通过昵称找到帮派成员对象*/
    private PartyMemberObject getMemberByName(Party party, String name) {
        if(party == null) {return null;}
        Collection<PartyMemberObject> values = party.getMembers().values();
        for (PartyMemberObject partyMember : values) {
            if (partyMember.getRoleName().equals(name)) {
                return partyMember;
            }
        }

        return null;
    }

    /**发送禁言列表*/
    public synchronized void sendDenyList(Role role) {
        RespOpenPlayerInfo respOpenPlayerInfo = new RespOpenPlayerInfo();
        Party party = getParty(role.getPartyId());
        if (party == null) {return ;}

        if (party.getDenyMap() != null) {
            List<PartyDeny> denyList = new ArrayList<>(party.getDenyMap().size());
            denyList.addAll(party.getDenyMap().values());
            respOpenPlayerInfo.setDenyList(denyList);
        }

        MessagePusher.pushMessage(role, respOpenPlayerInfo);
    }

    /**
     * 解除禁言
     * @param role
     * @param uid
     * @param name
     */
    public synchronized void cancelProhibitSpeaking(Role role, long uid, String name) {
        if (role == null) {return ;}

        Party party = getParty(role.getPartyId());
        if (party == null) {return ;}

        /**判断目标角色是否在对应帮派*/
        if (!isInParty(party, uid)) {
            MessagePusher.notify2Player(role, I18nId.PMT_308);
            return ;
        }

        /**判断是否有权限*/
        if (!isDenyPermission(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_340, "解除禁言");
            return ;
        }

        party.getDenyMap().remove(uid);
        party.save();

        sendDenyList(role);

        /**帮派聊天消息*/
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_341, name);
        npcPartyChat(party, content);

        /**邮件消息*/
        Role targetRole = SpringUtils.getRoleService().getOnlinePlayer(uid);
        if (targetRole != null) {
            String mailTitle = I18nIdDataPool.getI18nContent(I18nId.PMT_338);
            String mailContent = I18nIdDataPool.getI18nContent(I18nId.PMT_342);
            Mail mail = SpringUtils.getMailService().createMail(mailTitle, mailContent, 1 * TimeUtil.ONE_DAY);
            SpringUtils.getMailService().sendNewMail(targetRole, mail);
        }
    }

    /**
     * 获得日志
     * @param role
     * @param start
     * @param limit
     */
    public synchronized void getPartyLog(Role role, int start, int limit) {
        List<String> list = getLog(role, start, limit);
        if (!CollectionUtils.isEmpty(list)) {
            RespPartyLog respPartyLog = new RespPartyLog();
            respPartyLog.setStart(start);
            respPartyLog.setList(list);

            MessagePusher.pushMessage(role, respPartyLog);
        }
    }

    private List<String> getLog(Role role, int start, int limit) {
        List<String> list = new ArrayList<>();
        Party party = getParty(role);
        if (party == null) {
            return list;
        }

        PartyLog log = null;
        List<PartyLog> logs = new ArrayList<>(party.getLogs());
        logs.sort(Comparator.comparing(PartyLog::getTime).reversed());
        for (int i=start, end=start+limit>logs.size()?logs.size():start+limit; i<end; i++) {
            log = logs.get(i);
            String formatDate = TimeUtil.formatDate(new Date(log.getTime() * TimeUtil.ONE_SECOND), LOG_DATE_FORMAT);
            String content = I18nIdDataPool.getI18nContent(log.getId(), (Object[])log.getArgs());
            list.add(formatDate + " " + content);
        }

        return list;
    }

    /**帮派改名*/
    public synchronized void rename(Role role, String name, byte type) {
        if (role == null) {return ;}
        Party party = getParty(role.getPartyId());
        /**还没有帮派*/
        if (party == null) {
            MessagePusher.notify2Player(role, I18nId.PMT_319);
            return ;
        }
        /**不是帮主*/
        if (!isPartyLeader(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_345);
            return ;
        }


        /**判断是否有改头换面卡*/
        if (SpringUtils.getEquipService().getCount(Const.GAI_TOU_HUAN_MAIN_CARD, true, role) <= 0) {
            MessagePusher.notify2Player(role, I18nId.PMT_402);
            return ;
        }

        /**检测帮派名称是否合法*/
        boolean check = checkPartyName(role, name);
        if (check == false) {
            return ;
        }

        /**扣除道具*/
        SpringUtils.getEquipService().delRoloEquip(Const.GAI_TOU_HUAN_MAIN_CARD, 1, true, role);

        doRename(party, name);

    }

    /**执行帮派改名*/
    private void doRename(Party party, String name) {
        party.setPartyName(name);
        party.save();


        /**改所有人的称号*/
        /**在线的马上改*/
        /**不在线的则等上线再改，否则要拉起那么多玩家应该会有问题。。。*/
        Collection<PartyMemberObject> partyMembers = party.getMembers().values();
        for (PartyMemberObject partyMember : partyMembers) {
            Role role = roleService.getOnlinePlayer(partyMember.getRoleUid());
            if (role != null) {
                /**在线*/
                String jobName = getPartyJobName(partyMember);
                roleService.changeTitle(role, new TitleInfo(Const.TITLE_TYPE_PARTY, getTitle(name, jobName)));
            } else {
                /**不在线*/
                partyMember.setTitleChange(true);
            }
        }
    }

    /**检测帮派名称*/
    private boolean checkPartyName(Role role, String name) {
        /**不能是空白字符*/
        if (StringUtils.isBlank(name)) {
            MessagePusher.notify2Player(role, I18nId.PMT_348);
            return false;
        }

        /**不能少于2个字符*/
        if (name.length() < 2) {
            MessagePusher.notify2Player(role, I18nId.PMT_346);
            return false;
        }
        /**不能多于12个字符*/
        if (name.length() > 12) {
            MessagePusher.notify2Player(role, I18nId.PMT_347);
            return false;
        }
        /**不能已经存在的帮派名字*/
        if (isPartyNameExist(name)) {
            MessagePusher.notify2Player(role, I18nId.PMT_301);
            return false;
        }

        List<String> set = wordService.checkDirtyWords(name);
        if (set.size() >= 1) { //敏感词检测
            MessagePusher.pushMessage(role,new RespMsg("帮派名存在敏感词。"));
            return false;
        }

        return true;
    }

    /**
     * 修改帮派Icon
     */
    public synchronized void modifyPartyIcon(Role role, byte operType, String md5Value, String fileData) {
        if (role == null) {return ;}
        Party party = getParty(role);
        /**还没有帮派*/
        if (party == null) {
            MessagePusher.notify2Player(role, I18nId.PMT_319);
            return ;
        }
        /**不是帮主*/
        if (!isPartyLeader(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_345);
            return ;
        }
        /**系统自带图片*/
        if (operType == 2) {
            String fileName = md5Value;
            party.setIcon(fileName);
            party.save();
            openPartyDlg(role);
            notifyicon(role);
            MessagePusher.pushMessage(role,new RespNotifyMiscEx("帮派图标设置成功。"));
            Collection<PartyMemberObject> members = party.getMembers().values();
            List<Role> list = new ArrayList<Role>();
            if (members != null) {
                for (PartyMemberObject member : members) {
                    Role role1 = roleService.getPlayerBy(member.getRoleUid());
                    notifyicon(role1);
                }
            }
        }
    }
    /**
     * 发送帮派邮件
     * @param role
     * @param title
     * @param mailMsg
     */
    public void sendPartyMail(Role role, String title, String mailMsg) {
        if (role == null) {
            return;
        }
        Party party = getPartyByName(role.getPartyName());
        if (isSendMailPermission(role)) {
            boolean haveRemainCount = SpringUtils.getActivityService().isHaveRemainCount(role, ActivityType.PARTY_MAIL);
            if (haveRemainCount == false) {
                MessagePusher.pushMessage(role, new RespMsg("每天只能使用5次帮派传话功能。"));
                return;
            }

            String mailTitle = "帮派公告-" + title;
            String mailContent = mailMsg;
            Set<Long> uids = party.getMembers().keySet();
            MailService mailService = SpringUtils.getMailService();
            for (long uid : uids) {
                // TODO 只给在线玩家发？？
                Role member = roleService.getOnlinePlayer(uid);
                if (member == null) {continue;}
                Mail mail = mailService.createMail(mailTitle, mailContent, TimeUtil.ONE_DAY);
//                mailService.sendNewMail(member, mail);
            }

            SpringUtils.getActivityService().addFinishCount(role, ActivityType.PARTY_MAIL, 1);
            role.save();

            MessagePusher.pushMessage(role, new RespMsg("公告已发送。"));
        }
    }

    /**是否有发送帮派邮件权限*/
    private boolean isSendMailPermission(Role role) {
        byte permission = getPermission(role);
        return permission == Const.PARTY_PERMISSION_BZ || permission == Const.PARTY_PERMISSION_FBZ;
    }

    /**对应职位是不是管理职业*/
    private boolean isManager(String jobName) {
        if (Const.MANAGER_JOBS.contains(jobName)) {
            return true;
        }

        return false;
    }

    /**添加帮派日志*/
    private void addPartyLog(Party party, int i18nId, String[] args) {
        party.getLogs().add(new PartyLog(i18nId, args));
        /**超过最大数量时，删除超过数量的日志数据*/
        int size = party.getLogs().size();
        if (size > Const.LOG_MAX_COUNT) {
            for (int i=0, loop=size-Const.LOG_MAX_COUNT; i<loop; i++) {
                party.getLogs().remove(0);
            }
        }
        party.save();
    }

    /**是否禁止帮派发言*/
    public boolean isChatDeny(Role role) {
        Party party = getParty(role);
        if (party == null) {return true;}

        return party.getDenyMap().containsKey(role.getUid());
    }

    /**获得禁止帮派发言结束时间*/
    public long getChatDenyEndtime(Role role) {
        Party party = getParty(role);
        if (party == null) {return 0;}

        PartyDeny partyDeny = party.getDenyMap().get(role.getUid());
        if (partyDeny == null) {return 0;}

        return partyDeny.getEndTime();
    }

    /**帮派检测*/
    public void check() {
        Party party = null;
        Set<Long> uids = PartyDataPool.partyMap.keySet();
        for (long uid : uids) {
            party = PartyDataPool.partyMap.get(uid);
            if (party == null) {continue;}

            checkParty(party);
        }
    }

    private void checkParty(Party party) {
        if (party == null) {return ;}
        checkChatDeny(party);
        checkHeir(party);
        redBagHandler.checkPartyRedBag(party);
    }

    /**检测禁言已过有期，过期解除禁言*/
    private void checkChatDeny(Party party) {
        /**删除过期的禁言*/
        long now = System.currentTimeMillis();
        PartyDeny partyDeny = null;
        Set<Long> uids = party.getDenyMap().keySet();
        List<Long> del = null;
        for (long uid : uids) {
            partyDeny = party.getDenyMap().get(uid);
            if (partyDeny == null) {continue;}

            if (now > partyDeny.getEndTime() * TimeUtil.ONE_SECOND ) {
                if (del == null) {del = new ArrayList<>();}
                del.add(uid);
            }
        }

        if (del != null) {
            for (long uid : del) {
                party.getDenyMap().remove(uid);
                party.save();
            }
        }
    }

    /**检测帮主继承人是否到继承时间，到时间则继承*/
    private void checkHeir(Party party) {
        /**到期自动继承帮主*/
        long now = System.currentTimeMillis();
        if (party.getHeir() != null && party.getHeirEndTime() > 0 && now > party.getHeirEndTime()) {
            /**修改旧帮主的职位和称号*/
            String jobName = Const.PARTY_JOB_BANG_ZHONG;
            String job = jobName + ":" + getPartyTotalCount(party);
            List<Role> roleList = new ArrayList<>(2);
            long uid = party.getJobs().getLong(Const.PARTY_JOB_BANG_ZHU);
            PartyMemberObject partyMember = party.getMembers().get(uid);
            RoleView prevRoleView = new RoleView(partyMember.getRoleUid());
            if (partyMember != null) {
                partyMember.setJob(job);

                Role prevRole = SpringUtils.getRoleService().getOnlinePlayer(partyMember.getRoleUid());
                if (prevRole != null) {
                    roleService.changeTitle(prevRole, new TitleInfo(Const.TITLE_TYPE_PARTY, getTitle(party.getPartyName(), jobName)));
                    roleList.add(prevRole);
                } else {
                    /**不在线*/
                    partyMember.setTitleChange(true);
                }
            }

            /**修改新帮主的职位和称号*/
            jobName = Const.PARTY_JOB_BANG_ZHU;
            job = jobName + ":-1";
            String roleName = party.getHeir();
            partyMember = getPartyMember(party, roleName);
            String oldJobName = getPartyJobName(partyMember);
            RoleView currRoleView = new RoleView(partyMember.getRoleUid());
            if (partyMember != null) {
                partyMember.setJob(job);

                Role currRole = SpringUtils.getRoleService().getOnlinePlayer(partyMember.getRoleUid());
                if (currRole != null) {
                    roleService.changeTitle(currRole, new TitleInfo(Const.TITLE_TYPE_PARTY, getTitle(party.getPartyName(), jobName)));
                    roleList.add(currRole);
                } else {
                    /**不在线*/
                    partyMember.setTitleChange(true);
                }

                party.getJobs().remove(oldJobName);
                party.getJobs().setv(Const.PARTY_JOB_BANG_ZHU, partyMember.getRoleUid());
            }

            party.setHeir(null);
            party.setHeirEndTime(0);

            /**帮派日志*/
            addPartyLog(party, I18nId.PMT_356, new String[]{prevRoleView.getName(), currRoleView.getName(), currRoleView.getName()});

            party.save();

            for (Role role : roleList) {
                RespOpenPatry respOpenPatry = getRespOpenPatry(party);
                MessagePusher.pushMessage(role, respOpenPatry);
                RespPartyMembers respPartyMembers = getRespPartyMembers(party);
                MessagePusher.pushMessage(role, respPartyMembers);
                roleService.sendExtraAttribute(role);
            }
        }
    }

    private PartyMemberObject getPartyMember(Party party, String name) {
        if (party == null || name == null) {return null;}

        Collection<PartyMemberObject> memberObjects = party.getMembers().values();
        for (PartyMemberObject partyMemberObject : memberObjects) {
            if (name.equals(partyMemberObject.getRoleName())) {
                return partyMemberObject;
            }
        }

        return null;
    }

    public String getTitle(String partyName, String jobName) {
        return partyName + " " + jobName;
    }

    /**是否有入帮申请*/
    private boolean isHaveJoinRequest(Party party) {
        if (party == null) {return false;}

        return party.getReqJoin() != null && party.getReqJoin().size() > 0;
    }

    /**
     * 添加帮贡
     * @param role
     * @param value
     */
    public void addContrib(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        PartyMemberObject partyMember = getPartyMember(party, role);
        if (partyMember == null) {
            log.error("角色帮派对应成员不存在，roleUid:{}, partyId:{}", role.getUid(), party.getId());
            return ;
        }
        long before = partyMember.getContrib();

        long current = before + value;
        if (current > 2000000000) {
            current = 2000000000;
        }
        partyMember.setContrib((int) current);
        party.save();

        int added = (int) (current - before);
        if (added > 0) {
            SpringUtils.getRoleService().sendExtraAttribute(role);

            String content = I18nIdDataPool.getI18nContent(I18nId.PMT_404, added);
            MessagePusher.pushMessage(role, new RespNotifyMisc(content));
        }
    }

    /**
     * 消耗帮贡
     * @param role
     * @param value
     */
    public void substractContrib(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        PartyMemberObject partyMember = getPartyMember(party, role);
        if (partyMember == null) {
            log.error("角色帮派对应成员不存在，roleUid:{}, partyId:{}", role.getUid(), party.getId());
            return ;
        }
        long before = partyMember.getContrib();

        long current = before - value;
        if (current < 0) {
            current = 0;
        }
        partyMember.setContrib((int) current);
        party.save();

        int substracted = (int) (before - current);
        if (substracted > 0) {
            SpringUtils.getRoleService().sendExtraAttribute(role);

            String content = I18nIdDataPool.getI18nContent(I18nId.PMT_408, substracted);
            MessagePusher.pushMessage(role, new RespNotifyMisc(content));
        }
    }

    /**
     * 添加帮派活力
     * @param role
     * @param value
     */
    public void addVitality(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        PartyMemberObject partyMember = getPartyMember(party, role);
        if (partyMember == null) {
            log.error("角色帮派对应成员不存在，roleUid:{}, partyId:{}", role.getUid(), party.getId());
            return ;
        }
        long before = partyMember.getVitality();

        long current = before + value;
        if (current > 2000000000) {
            current = 2000000000;
        }
        partyMember.setVitality((int) current);
        /**增加本周活力*/
        partyMember.setCurrWeekVitality(partyMember.getCurrWeekVitality() + value);
        party.save();

        int added = (int) (current - before);
        if (added > 0) {
            String content = I18nIdDataPool.getI18nContent(I18nId.PMT_405, added);
            MessagePusher.pushMessage(role, new RespNotifyMisc(content));
        }
    }

    /**
     * 添加帮派建设度
     * @param role
     * @param value
     */
    public void addConstruction(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        long before = party.getJianshe();

        long current = before + value;
        if (current > 2000000000) {
            current = 2000000000;
        }

        party.setJianshe((int) current);
        party.save();
    }

    /**
     * 扣除帮派建设度
     * @param role
     * @param value
     */
    public void substractConstruction(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        int before = party.getJianshe();
        int current = before - value;
        if (current < 0) {
            current = 0;
        }
        party.setJianshe(current);

        party.save();
    }

    /**
     * 添加帮派资金
     * @param role
     * @param value
     */
    public void addCapital(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        long before = party.getCapital();

        long current = before + value;
        if (current > 2000000000) {
            current = 2000000000;
        }

        party.setCapital((int) current);
        party.save();

        /** 产生一个帮派资金改变事件 */
        EventDispatcher.getInstance().fireEvent(new PartyCapitalChangeEvent(EventType.PARTY_CAPITAL_CHANGE, role, party));
    }

    /**
     * 扣除帮派资金
     * @param role
     * @param value
     */
    public void substractCapital(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        int before = party.getCapital();
        int current = before - value;
        if (current < 0) {
            current = 0;
        }
        party.setCapital(current);

        party.save();

        /** 产生一个帮派资金改变事件 */
        EventDispatcher.getInstance().fireEvent(new PartyCapitalChangeEvent(EventType.PARTY_CAPITAL_CHANGE, role, party));
    }

    /**
     * 请求捐献
     * @param role
     * @param value
     */
    public void reqDonate(Role role, NPC npc, int value) {
        role.setConfirm(new PartyDonateConfirm(value));
        role.pushTempCache("talk_npcId", npc.getId());

        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_368, AsktaoUtil.getMoneyFormat(value));
        RespConfirm respConfirm = new RespConfirm();
        respConfirm.setTips(content);
        respConfirm.setConfirm_type("");
        MessagePusher.pushMessage(role, respConfirm);
    }

    /**
     * 捐献
     * @param role
     * @param value
     */
    public void donate(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        /**判断是否有足够的金钱*/
        if (role.getMoney() < value) {
            String content = I18nIdDataPool.getI18nContent(I18nId.PMT_406) + Const.LEAVE_BUTTON;

            int talkNpcId = role.getTempCache("talk_npcId", 0);
            NPC npc = SpringUtils.getMapService().getNpc(talkNpcId);
            SpringUtils.getNpcService().sendNpcContent(role, npc, content);
            return ;
        }

        /**扣钱*/
        SpringUtils.getRoleService().subtractMoney(role, value, Reason.PARTY_DONATE);

        /**加活力值*/
        int vitality = value / 10000;
        addVitality(role, vitality);

        /**加帮派资金*/
        int capital = value / 10;
        addCapital(role, capital);

        /**加帮派俸禄*/
        int salary = value * 9 / 10;
        addSalary(role, salary);

        String formatMoney = AsktaoUtil.getMoneyFormat(value);
        /**帮派日志*/
        addPartyLog(party, I18nId.PMT_371, new String[]{role.getName(), formatMoney, String.valueOf(vitality)});

        /**帮派聊天消息*/
        String content = I18nIdDataPool.getI18nContent(I18nId.PMT_370, role.getName(), formatMoney, /*String.valueOf(*/vitality/*)*/, AsktaoUtil.getMoneyFormat(capital), AsktaoUtil.getMoneyFormat(salary));
        npcPartyChat(party, content);

        /**提示信息*/
        content = I18nIdDataPool.getI18nContent(I18nId.PMT_369, formatMoney, vitality);
        SpringUtils.getTeamService().pushMessage(role, new RespNotifyMisc(content));
    }

    /**
     * 添加帮派俸禄
     * @param role
     * @param value
     */
    public void addSalary(Role role, int value) {
        if (role == null) {return ;}
        if (value <= 0) {return ;}

        Party party = getParty(role);
        if (party == null) {return ;}

        long before = party.getFenglu();

        long current = before + value;
        if (current > 2000000000) {
            current = 2000000000;
        }

        party.setFenglu((int) current);
        party.save();
    }

    /**
     * (批量)研发技能
     * @param role
     * @param skillNo
     * @param addLevel 批量时传大于0的值
     * @param addPoint
     */
    public void developSkill(Role role, short skillNo, int addLevel, int addPoint) {
        if (role == null) {return ;}
        Party party = getParty(role);
        if (party == null) {
            MessagePusher.notify2Player(role, I18nId.PMT_319);
            return ;
        }

        /**中级及以上等级帮派才可以研发*/
        if (party.getLevel() <= 1) {
            MessagePusher.notify2Player(role, I18nId.PMT_377);
            return ;
        }

        /**判断权限*/
        if (!isPartyLeader(role)) {
            MessagePusher.notify2Player(role, I18nId.PMT_378);
            return ;
        }

        /**找不到对应的技能*/
        NutMap skill = getSkill(party, skillNo);
        if (skill == null) {
            return ;
        }

        int currPoint = skill.getInt("currJindu");
        int skillLevel = skill.getInt("skillLevel");
        Skill skillSet = SpringUtils.getSkillService().getSkillInfo(skillNo);
        if (skillSet == null) {
            MessagePusher.notify2Player(role, I18nId.PMT_382);
            return ;
        }
        String skillName = skillSet.getSkillName();
        if (addLevel > 0) {
            addPoint = getUpgradePoint(skillName, currPoint, (short)skillLevel, (short)addLevel);
        }

//        if (addPoint <= 0) {
//            return ;
//        }


        /**需求的帮派资金*/
        int reqCapital = 74 * addPoint;
        /**需求的建设度*/
        int reqConstruction = addPoint;

        /**判断资源是否足够*/
//        if (party.getCapital() < reqCapital) {
//            MessagePusher.notify2Player(role, I18nId.PMT_374);
//            return ;
//        }
//        if (party.getJianshe() < reqConstruction) {
//            MessagePusher.notify2Player(role, I18nId.PMT_375);
//            return ;
//        }

        /**等级已达上限*/
//        if (skillLevel >= Const.MAX_PARTY_SKILL_LEVEL) {
//            MessagePusher.notify2Player(role, I18nId.PMT_376);
//            return ;
//        }

//        if (addLevel > 0 && (skillLevel + addLevel > Const.MAX_PARTY_SKILL_LEVEL)) {
//            MessagePusher.notify2Player(role, I18nId.PMT_379);
//            return ;
//        }

        /**扣除资源*/
//        substractConstruction(role, reqConstruction);
//        substractCapital(role, reqCapital);

        int newLevel = skillLevel;
        if (addLevel > 0) {
            /**批量研发*/
            newLevel = skillLevel + addLevel;
            int total = getLevelTotalPoint(skillName, (short) newLevel);
            skill.setv("skillLevel", newLevel);
            skill.setv("currJindu", 0);
            skill.setv("total", total);
        } else {
            int newPoint = currPoint + addPoint;
            int total = getLevelTotalPoint(skillName, (short) skillLevel);
            if (newPoint >= total) {
                /**升级*/
                newLevel = skillLevel+1;
                skill.setv("skillLevel", newLevel);
                skill.setv("currJindu", 0);
                skill.setv("total", getLevelTotalPoint(skillName, (short)newLevel));
            } else {
                skill.setv("currJindu", newPoint);
            }
        }

        party.save();

        RespOpenPatry respOpenPatry = getRespOpenPatry(party);
        MessagePusher.pushMessage(role, respOpenPatry);

        if (newLevel > skillLevel) {
            String content = I18nIdDataPool.getI18nContent(I18nId.PMT_381, skillName, newLevel);
            MessagePusher.pushMessage(role, new RespNotifyMisc(content));
        }
    }

    private NutMap getSkill(Party party, short skillNo) {
        if (party == null || party.getSkills() == null) {return null;}

        List<NutMap> skills = party.getSkills();
        for (NutMap skill : skills) {
            if (skillNo == skill.getInt("skillId")) {
                return skill;
            }
        }

        return null;
    }

    public int getLevelTotalPoint(String skillName, short level) {
        if (level == 0) {
            return 1350000;
        }

        if (PetDataPool.isInnateSkill(skillName)) {
            if (level < 180) {
                return 4 * level * level + 400 * level;
            } else if (level <= Const.MAX_PARTY_SKILL_LEVEL) {
                return (int) Math.floor(0.28 * level * level * level - 45 * level * level + 32000);
            } else {
                return 0;
            }
        } else {
            return 4 * level * level + 400 * level;
        }
    }

    public int getUpgradePoint(String skillName, int currPoint, short currLevel, short upLevel) {
        if (upLevel == 0) {return 0;}

        int levelTotalPoint = getLevelTotalPoint(skillName, currLevel);
        int point = levelTotalPoint - currPoint;

        if (upLevel > 1) {
            for (int i=1; i<= upLevel-1; i++) {
                int upPoint = getLevelTotalPoint(skillName, (short) (currLevel + i));
                point += upPoint;
            }
        }

        return point;
    }

    /**获得研发的技能等级*/
    public short getSkillLevel(Role role, int skillId) {
        Party party = getParty(role);
        if (party == null) {return 0;}

        NutMap skill = getSkill(party, (short) skillId);
        if (skill == null) {return 0;}

        return (short) skill.getInt("skillLevel", 0);
    }

    /**获得帮派成员数量*/
    public short getMemberCount(Party party) {
        if (party != null && party.getMembers() != null) {
            return (short) party.getMembers().size();
        }
        return 0;
    }
}
